﻿using Qy.Common;
using PetaPoco;
using PetaPoco.Core;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Qy.Repository
{
    [AppService]
    public class BaseRepository<TEntity, TDbContext>
        where TEntity : class
        where TDbContext : PetaPocoDbContext
    {
        public BaseRepository(TDbContext dbContext)
        {
            DbContext = dbContext;
        }

        public virtual TDbContext DbContext
        {
            get;
            set;
        }

        /// <summary>
        /// 默认PetaPocoDatabase实例
        /// </summary>
        /// <returns></returns>
        protected virtual IDatabase CreateDAO()
        {
            return DbContext;
        }

        /// <summary>
        /// 把实体entity添加到数据库
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<object> InsertAsync(TEntity entity)
        {
            return await CreateDAO().InsertAsync(entity);
        }

        /// <summary>
        /// 根据主键把实体entiy更新到数据库 
        /// </summary>
        /// <param name="entity"></param>
        public virtual async Task<int> UpdateAsync(TEntity entity, int primaryKeyValue)
        {
            return await CreateDAO().UpdateAsync(entity, primaryKeyValue);
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        public virtual async Task<int> UpdateAsync(TEntity entity)
        {
            return await CreateDAO().UpdateAsync(entity);
        }

        /// <summary>
        /// 从数据库删除实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<int> DeleteAsync(TEntity entity)
        {
            if (entity == null)
            {
                return 0;
            }
            return await CreateDAO().DeleteAsync(entity);
        }

        /// <summary>
        /// 根据主键删除实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<int> DeleteByPriKeyAsync(int primaryKeyValue)
        {
            return await CreateDAO().DeleteAsync<TEntity>(primaryKeyValue);
        }


        /// <summary>
        /// 依据主键检查实体是否存在于数据库 
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public async Task<bool> ExistsAsync(object entityId)
        {
            return await CreateDAO().ExistsAsync<TEntity>(entityId);
        }


        /// <summary>
        /// 依据EntityId获取单个实体
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> GetAsync(object entityId)
        {
            return await CreateDAO().SingleOrDefaultAsync<TEntity>(entityId);
        }


        /// <summary>
        /// 依据EntityId获取单个实体
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public virtual TEntity Get(object entityId)
        {
            return CreateDAO().SingleOrDefault<TEntity>(entityId);
        }

        /// <summary>
        /// 获取所有实体（仅用于数据量少的情况）
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetAllAsync(string orderBy)
        {

            PocoData data = PocoData.ForType(typeof(TEntity), new ConventionMapper());
            Sql sql = Sql.Builder.Select("*").From(new object[] { data.TableInfo.TableName });
            if (!string.IsNullOrEmpty(orderBy))
            {
                sql.OrderBy(new object[] { orderBy });
            }
            return await CreateDAO().FetchAsync<TEntity>(sql);
        }

        /// <summary>
        /// 获取所有实体 返回集合泛型（仅用于数据量少的情况）
        /// </summary>
        /// <returns></returns>
        public async Task<List<TEntity>> GetAllListAsync(string orderBy)
        {

            PocoData data = PocoData.ForType(typeof(TEntity), new ConventionMapper());
            Sql sql = Sql.Builder.Select("*").From(new object[] { data.TableInfo.TableName });
            if (!string.IsNullOrEmpty(orderBy))
            {
                sql.OrderBy(new object[] { orderBy });
            }
            return await CreateDAO().FetchAsync<TEntity>(sql);
        }

    }
}
